package com.youhome.common.handler;

import com.youhome.common.exception.CustomException;
import com.youhome.common.exception.FieldError;
import com.youhome.common.response.Result;
import com.youhome.common.response.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.expression.AccessException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.lang.Nullable;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import javax.persistence.PersistenceException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by chen365 on 2019/01/23.
 */
@ControllerAdvice
@Slf4j
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(HttpClientErrorException.Unauthorized.class)
    public ResponseEntity<Result> handleUnauthorizedException(HttpClientErrorException.Unauthorized e) {
        log.error("===>>Unauthorized", e);
        return ResponseEntity.ok().body(new Result(ResultCode.FAIL_LOGIN, e.getMessage()));
    }

    @ExceptionHandler(CustomException.class)
    public ResponseEntity<Result> handleCustomException(CustomException e) {
        log.error("===>>CustomException", e);
        return ResponseEntity.ok().body(new Result(e.getResultCode(), e.getObject()));
        // return ResponseEntity.badRequest().body(new Result(e.getResultCode(), e.getObject()));
    }

    @Override
    public ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        BindingResult result = ex.getBindingResult();
        List<FieldError> errors = result.getFieldErrors().stream().map(
                error -> new FieldError(error.getField(), error.getDefaultMessage())
        ).collect(Collectors.toList());
        return ResponseEntity.ok().body(new Result(ResultCode.ERROR_PARAMETER, errors));
        //return ResponseEntity.ok().body(new Result(ResultCode.ERROR_PARAMETER, errors));
    }

    @Override
    protected ResponseEntity<Object> handleExceptionInternal(Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
        System.err.println("ex==>>" + ex.getMessage());
        if (ex instanceof MethodArgumentTypeMismatchException) {
            System.err.println("====>>MethodArgumentTypeMismatchException");
            return ResponseEntity.ok().body(new Result(ResultCode.ERROR_PARAMETER, ex.getMessage()));
        }
        if (ex instanceof BindException) {
            System.err.println("====>>BindException");
            BindException e = (BindException) ex;
            BindingResult bindingResult = e.getBindingResult();
            List<FieldError> errors = bindingResult.getFieldErrors().stream().map(
                    error -> new FieldError(error.getField(), error.getDefaultMessage())
            ).collect(Collectors.toList());
            return ResponseEntity.ok().body(new Result(ResultCode.ERROR_PARAMETER, errors));
        }
        if (ex instanceof HttpClientErrorException.Unauthorized) {
            System.err.println("401");
            return ResponseEntity.status(401).build();
        }
        if (ex instanceof AccessException) {
            System.err.println("403");
            return ResponseEntity.status(403).build();
        }

        if (ex instanceof IllegalArgumentException || ex instanceof IllegalStateException) {
            return ResponseEntity.ok().body(new Result(ResultCode.ERROR_PARAMETER, ex.getMessage()));
        }
        if (ex instanceof PersistenceException || ex instanceof BadSqlGrammarException) {
            return ResponseEntity.ok().body(new Result(ResultCode.ERROR_SQL, ex.getMessage()));
        }
        if (ex instanceof NullPointerException) {
            return ResponseEntity.ok().body(new Result(ResultCode.FAIL, ex.getMessage()));
        }
        return super.handleExceptionInternal(ex, body, headers, status, request);
    }

}
